package core;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import core.entities.Item;
import core.entities.Stats;
import core.storage.BinarySerializer;

/**
 * Class modeling the whole profile of a player who will be logged
 * 
 * @author Alexandre Boursier, Olivier Cacciuttolo
 * @version 1.0.0 initial version
 * @version 1.1.0 serialization allowed
 * 
 */
public class Profile implements Serializable {

	private static final long serialVersionUID = -213223093818811184L;

	// Constants useful for serialization
	private static final String REACTION_TIME = "ReactionTime";
	private static final String STORE_POINTS = "StorePoints";
	private static final String ITEM_BOUGHT = "ItemBought";
	private static final String STATS = "Stats";

	/**
	 * Name of the created profile
	 */
	private String name;

	/**
	 * The number of points allowing to buy some items in the store (awards)
	 */
	private int storePoints;

	/**
	 * The average reaction time of the current profile
	 */
	private double reactionTime;

	/**
	 * The stats used in order to unlock achievements (and then awards)
	 */
	private Stats stats;

	/**
	 * List of the item bought to the store
	 */
	private List<Item> itemsBought;

	/**
	 * First constructor
	 * 
	 * @param name
	 */
	@SuppressWarnings("unchecked")
	public Profile(String name) {

		this.name = name;

		
		Object o = BinarySerializer.load("../ressources/files/" + name + ".bin");
		if (o == null) {
			this.storePoints = 0;
			this.reactionTime = 3.00;
			this.itemsBought = new ArrayList<Item>();
			this.itemsBought.add(Item.TOTEM_0);
			this.stats = new Stats();
			this.saveProfile();
		} else {
			HashMap<String, Object> map = (HashMap<String, Object>) o;
			this.storePoints = (Integer) map.get(STORE_POINTS);
			this.reactionTime = (Double) map.get(REACTION_TIME);
			this.itemsBought = (List<Item>) map.get(ITEM_BOUGHT);
			this.stats = (Stats) map.get(STATS);
		}
	}

	/**
	 * Second constructor
	 * 
	 * @param name
	 *            the name of the targeted profile
	 * @param storePoints
	 *            the name of the points to the store
	 * @param reactionTime
	 *            the average reaction time of the targeted profile
	 */
	@SuppressWarnings("unchecked")
	public Profile(String name, int storePoints, double reactionTime) {

		this.name = name;
		this.storePoints = storePoints;
		this.reactionTime = reactionTime;

		Object o = BinarySerializer.load("../ressources/files/" + name + ".bin");
		if (o == null) {
			this.itemsBought = new ArrayList<Item>();
			this.stats = new Stats();
		} else {
			HashMap<String, Object> map = (HashMap<String, Object>) o;
			this.itemsBought = (List<Item>) map.get(ITEM_BOUGHT);
			this.stats = (Stats) map.get(STATS);
		}
	}

	/**
	 * Default constructor
	 */
	public Profile() {
		this.name = "";
		this.storePoints = 0;
		this.reactionTime = 3.00;
		this.itemsBought = new ArrayList<Item>();
		this.stats = new Stats();
	}

	/**
	 * Add an item to the list
	 * 
	 * @param target
	 *            the targeted item
	 * 
	 */
	public void addItem(Item target) {
		if (!this.itemsBought.contains(target))
			itemsBought.add(target);
	}

	/**
	 * Remove an item of the list
	 * 
	 * @param target
	 *            the targeted item
	 * 
	 */
	public void removeItem(Item target) {
		itemsBought.remove(target);
	}

	/**
	 * Clear the item bought list
	 */
	public void clearItems() {
		itemsBought.clear();
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the storePoints
	 */
	public int getStorePoints() {
		return storePoints;
	}

	/**
	 * @param storePoints
	 *            the storePoints to set
	 */
	public void setStorePoints(int storePoints) {
		this.storePoints = storePoints;
	}

	/**
	 * @return the reactionTime
	 */
	public double getReactionTime() {
		return reactionTime;
	}

	/**
	 * @param reactionTime
	 *            the reactionTime to set
	 */
	public void setReactionTime(double reactionTime) {
		this.reactionTime = reactionTime;
	}

	/**
	 * @return the stats
	 */
	public Stats getStats() {
		return stats;
	}

	/**
	 * @param stats
	 *            the stats to set
	 */
	public void setStats(Stats stats) {
		this.stats = stats;
	}

	/**
	 * 
	 * @return all items bought
	 */
	public List<Item> getItemsBought() {
		return itemsBought;
	}

	/**
	 * Serialization of the profile for the next launch of the game
	 */
	public void saveProfile() {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put(REACTION_TIME, this.reactionTime);
		map.put(STORE_POINTS, this.storePoints);
		map.put(ITEM_BOUGHT, this.itemsBought);
		map.put(STATS, this.stats);
		BinarySerializer.store(map, "../ressources/files/" + this.name + ".bin");
	}
}
